﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Office2010.PowerPoint;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using OpenPowerPoint.Collection;
using OpenPowerPoint.Slides.Elements;
using Shape = OpenPowerPoint.Slides.Elements.Shape;

namespace OpenPowerPoint.Slides
{
    /// <summary>
    /// Represents a single slide
    /// </summary>
    public class Slide : BaseSlide
    {
        #region Load/Save
        /// <summary>
        /// Generates a slide out of a SlidePart
        /// </summary>
        /// <param name="part">The SlidePart to generate a slide from</param>
        /// <returns>Returns the Slide Object</returns>
        public static Slide Load(SlidePart part)
        {
            var ret = new Slide();
            ret.LoadCommonSlideData(part.Slide.CommonSlideData);

            if (part.Slide.Show != null)
                ret.Hidden = !BooleanValue.ToBoolean(part.Slide.Show);
            else
                ret.Hidden = false;

            return ret;
        }

        /// <summary>
        /// Saves the slide into the presentation object
        /// </summary>
        /// <param name="presentation">The destination presentation</param>
        /// <returns>A slideId Object for the groups</returns>
        public SectionSlideIdListEntry Save(ref PresentationPart presentation)
        {
            string rid = RelationResolver.GetNextRelationId();

            var slide = presentation.AddNewPart<SlidePart>(rid);
            slide.Slide = new DocumentFormat.OpenXml.Presentation.Slide { Show = Hidden };

            return new SectionSlideIdListEntry { Id = RelationResolver.GetNextSlideId() };
        }

        /// <summary>
        /// Performs a cleanup of all temporary data
        /// </summary>
        public void Saved()
        {

        }

        #endregion

        #region Initializer

        public Slide()
        { }

        #endregion

        #region Properties
        public static readonly DependencyProperty HiddenProperty =
            DependencyProperty.Register("Hidden", typeof(bool), typeof(Slide), new PropertyMetadata(default(bool), (o, e) => ((Slide)o).OnPropertyChanged(o, new SProperty(HiddenProperty, e.OldValue, e.NewValue))));

        /// <summary>
        /// Determines whether the slide will be shown when presented
        /// </summary>
        public bool Hidden
        {
            get { return (bool)GetValue(HiddenProperty); }
            set { SetValue(HiddenProperty, value); }
        }

        public static readonly DependencyProperty SlideMasterProperty =
            DependencyProperty.Register("SlideMaster", typeof(SlideMaster), typeof(Slide), new PropertyMetadata(default(SlideMaster), (o, e) => ((Slide)o).OnPropertyChanged(o, new SProperty(SlideMasterProperty, e.OldValue, e.NewValue))));

        public SlideMaster SlideMaster
        {
            get { return (SlideMaster)GetValue(SlideMasterProperty); }
            set { SetValue(SlideMasterProperty, value); }
        }

        public static readonly DependencyProperty SlideLayoutProperty =
            DependencyProperty.Register("SlideLayout", typeof(SlideLayout), typeof(Slide), new PropertyMetadata(default(SlideLayout), (o, e) => ((Slide)o).OnPropertyChanged(o, new SProperty(SlideLayoutProperty, e.OldValue, e.NewValue))));

        public SlideLayout SlideLayout
        {
            get { return (SlideLayout)GetValue(SlideLayoutProperty); }
            set { SetValue(SlideLayoutProperty, value); }
        }

        #region Functions
        //Here are mainly call-trough functions

        /// <summary>
        /// Whether the slide is hidden or not
        /// </summary>
        /// <param name="hidden"></param>
        /// <returns>The instance itself to work with</returns>
        public Slide SetHidden(bool hidden)
        {
            Hidden = hidden;
            return this;
        }
        #endregion

        #endregion

        #region INotify
        private new void OnPropertyChanged(object sender, SProperty property)
        {
            if (sender is Theme)
            {
                base.UpdateColor((Color)property.OldValue, (Color)property.NewValue);
                return;
            }

            base.OnPropertyChanged(sender, property);
        }
        #endregion
    }
}
